package client;
import java.io.*;

public class BeenTree {
    private Node root;
    public static int level;

    public BeenTree() {
        super();
        root = null;


    }

    public void setRoot(Node root) {
        this.root = root;
    }

    public Node getRoot() {
        return root;
    }


    public boolean isEmpty() {
        if (this.root == null) {
            return true;
        }
        return false;
    }

    public boolean addValue(int value) {
        Node insertNode = new Node(value);

        if (this.isEmpty()) {

            this.setRoot(insertNode);


            return true;
        } else {

            findPosition(value);

        }


        return false;
    }

    public void findPosition(int value) {
        Node add = new Node(value);
        Node compare = root;

        while (compare != null) {
            add.setPredecesor(compare);
            if (compare.getValue() > value) {
                compare = compare.getLChild();

            } else {
                compare = compare.getRChild();
            }
        }
        if (add.getPredecesor().getValue() > value || add.getPredecesor().getValue() == value) {
            add.getPredecesor().setLChild(add);
        }
        if (add.getPredecesor().getValue() < value) {
            add.getPredecesor().setRChild(add);
        }
    }

    public Node Search(int value) {
        level = 0;
        Node comp;
        // Node not = new Node();
        if (!this.isEmpty()) {
            comp = this.getRoot();
            boolean found = false;


            while (!found) {
                level = level + 1;
                if (comp.getValue() == value) {
                    return comp;
                } else if (comp.getValue() < value) {
                    if (comp.getRChild() != null)
                        comp = comp.getRChild();
                    else
                        return null;

                } else if (comp.getValue() > value) {
                    if (comp.getLChild() != null)
                        comp = comp.getLChild();
                    else
                        return null;

                }

            }
        }
        return null;
    }

    public void transplant(Node trans, Node trans2) {
        if (trans.getPredecesor() == null) {
            this.setRoot(trans2);
            this.getRoot().setPredecesor(null);
        } else {
          //  System.out.println("entra else");
            if (trans2 != null) {
                trans.setValue(trans2.getValue());
                if (trans2.getLChild() != null) {
                  //  System.out.println("1");
                    trans.setLChild(trans2.getLChild());
                } else {
                    //System.out.println("2");
                    trans.setLChild(null);
                }
                if (trans2.getRChild() != null) {
                    System.out.println("3");
                    trans.setRChild(trans2.getLChild());
                } else {
                    System.out.println("4");
                    trans.setRChild(null);
                }
                if (trans2.getPredecesor() != null) {
                    System.out.println("5");
                    trans.setPredecesor(trans2.getPredecesor());
                } else {
                    System.out.println("6");
                    trans.setPredecesor(null);
                }
            } else {
                trans.setPredecesor(null);
                trans = null;

            }

        }

    }

    public void delete(int value) {
        Node toDelete;
        if (!this.isEmpty()) {
            toDelete = this.Search(value);
            if(toDelete !=null)
            delete(toDelete, value);
        }


    }

    public Node nodeMin(Node branch) {
        System.out.println("Min");
        if( branch.getLChild() == null){
            System.out.println("Min if");
            return branch;
        }
        while (branch.getLChild() != null) {
            System.out.println("while");
            branch = branch.getLChild();
        }

        return branch;
    }

    public void delete(Node to_delete, int value) {
        Node min;
        Node comp;
        Node del = new Node();
        if (to_delete.getLChild() == null & to_delete.getRChild() == null) {
            if (to_delete.getPredecesor() == null) {
                this.root = null;
            } else {
                comp = this.getRoot();
                boolean found = false;


                while ((!found) & (comp != null)) {

                    if (comp.getValue() == value) {
                        found = true;
                        comp = comp.getPredecesor();
                        if (comp.getValue() > value) {
                            comp.setLChild(null);
                        } else {
                            comp.setRChild(null);
                        }


                    } else if (comp.getValue() < value) {
                        if (comp.getRChild() != null)
                            comp = comp.getRChild();


                    } else if (comp.getValue() > value) {
                        if (comp.getLChild() != null)
                            comp = comp.getLChild();


                    }

                }
            }

        } else {
            if (to_delete.getLChild() == null) {
                System.out.println("entra antes de transp");
                transplant(to_delete, to_delete.getRChild());
            } else {
                if (to_delete.getRChild() == null) {
                    transplant(to_delete, to_delete.getLChild());
                } else {
                    //delete when node to_delete has the two branches with children
                    System.out.println("entra delete opcion ramas ");
                   Node node= this.Sucesor(value);
                    if (node!=null){
                   to_delete.setValue(node.getValue());
                    //Right
                    if((node.getRChild()!=null) & ( node.getPredecesor()!=null))
                    node.getPredecesor().setRChild(node.getRChild());
                    

                    else // node.getPredecesor().setRChild(null);
                  // if(node.getRChild()!=null & node.getPredecesor()!=null )
                   // node.getRChild().setPredecesor(node.getPredecesor());
                    
               /***************************************
                * node.getPredecesor().setLChild(null);
                * *************************************/
                    if(node.getPredecesor().getLChild()!=null & node.getPredecesor()!=null) {
                       if( node.getPredecesor().getLChild().getValue() ==value) {
                           node.getPredecesor().setLChild(null);
                       }//else // node.getPredecesor().setRChild(null);
                    }
                    if (node.getPredecesor().getLChild()!=null){
                        System.out.println("entra if delete");
                       // if(node.getPredecesor().getLChild().getValue()==node.getValue()){
                       if(node.getPredecesor().getLChild().getValue()==node.getValue()){
                           node.getPredecesor().setLChild(null);}}
                        if (node.getPredecesor().getRChild()!=null){
                        
                       // System.out.println("entra else delete");
                       if(node.getPredecesor().getRChild().getValue()==node.getValue())
                        {
                            System.out.println("Rchild = null");
                            node.getPredecesor().getRChild().setValue(0);
                        node.getPredecesor().setRChild(null);
                       }
                    }
                
                  //  to_delete.setRChild(rChild);
                   // transplant(to_delete, this.Sucesor(value));
                    //if (min.getPredecesor().getValue() != value) {
                    // transplant(min () );
                }
                }
            }
        }
    }

public Node Sucesor (int value ) {
    Node node= this.Search(value);
    if (node!=null){
    //System.out.println("antes de buscar el minimo");
    //    System.out.println(node.getValue());
    }

    return this.nodeMin(node.getRChild());
    
}

    public void printFile() {
        System.out.println("entra archivo");
    File tree_struct;
    tree_struct = new File ("C:\\Tree_Structure.txt");
    
        try{
            FileWriter w = new FileWriter(tree_struct);
            BufferedWriter bw = new BufferedWriter(w);
            PrintWriter wr = new PrintWriter(bw); 
        this.to_print(this.root, wr, bw);
                wr.close();
                bw.close();}
         catch (IOException e){
            
        }
        
    
   System.out.println("termina archivo");
        
    }

    private void to_print(Node to_write, PrintWriter wr, BufferedWriter bw ) {
                 
       
                wr.write("Node value: ");
        wr.write(Integer.toString(to_write.getValue()));
                if (to_write.getLChild()!=null)
                {
                wr.write(". Left Child: ");
                wr.write(Integer.toString(to_write.getLChild().getValue()));
                    
                }
                if (to_write.getRChild()!=null)
                {
                wr.write(". Right Child: ");
                wr.write(Integer.toString(to_write.getRChild().getValue()));
                    
               }
        
        if (to_write.getPredecesor()==null){
        wr.write(" Is Root ");
        }else { 
                wr.write (" .Predecessor ");
            wr.write(Integer.toString(to_write.getPredecesor().getValue()));}
        wr.write("\r\n");
            if (to_write.getLChild()!=null)
        to_print (to_write.getLChild() ,wr, bw);   
        if (to_write.getRChild()!=null)
        to_print (to_write.getRChild() ,wr, bw);
    }
    }
